<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>解析UIL数据</title>
    <script src="/dist/base.js"></script>
</head>
<body>
    <script>
        Class(function UILData(){
            const _this = this;
            var data, _key = 'input', _index=0 , promise, _name, _cache = {};
            !async function(){
                data = await get('/assets/data/uil-lbm.json');
                promise.resolve();
            }();
            this.key = key => {
                _key = key;
                return this;
            }
            this.name = name => {
                _name = name;
                return this;
            }
            this.index = index => {
                _index = index;
                return this;
            }
            this._getName = (attr) => {
                switch(_key.toLowerCase()){
                    case 'mesh':
                        return `MESH_Element_${_index}_${_name}${attr}`;
                    case 'element':
                        return `INPUT_P_Element_${_index}_${_name}_config_${attr}`;
                    case 'input':
                    default:
                        return `INPUT_Config_${_index}_${_name}_${attr}`;
                }
            }

            this._getAllRelated = () => {
                let __name = this._getName(''), _data = {};
                
                Object.keys(data).map($key => {
                    if($key.includes(__name)){
                        _data[$key.replace(__name, '')] = data[$key];
                    }
                })
                return _data;
            }

            this.get = $key => {
                if(!$key) {
                    return this._getAllRelated();
                } else {
                    return data[this._getName($key)];
                }
            }

            this.set = data => {
                Object.keys(data).map($key => {
                    _cache[this._getName($key)] = data[$key];
                })
                return _cache;
            }
            this.ready = () => {
                promise = Promise.create();
                return promise;
            }
            function logPath(key, value) {
                _cache[key] = value;
            }

            function getLayers(sceneName, {layers}){
                let _layers = [];
                const _ = index => {
                    let prefix = `INPUT_Config_${index}_${sceneName}_`;
                    Object.keys(data).map(key => {
                        if(key.includes(prefix)) {
                           _layers[index] = _layers[index] || {};
                           logPath(key, data[key]);
                           _layers[index][key.replace(prefix, '')] = {
                               value: data[key],
                               key
                           };
                        }
                    })
                }
                for(var i = 0; i < layers+1; i++) {
                    _(i);
                }
                return _layers;
            }

            function getScenes(scenes) {
                let _scenes = [];
                const _ = key => key.match(/INPUT_scenelayout_(.*?)_data/)[1];
                scenes.map(key => {
                    logPath(key, data[key]);
                    _scenes.push({
                        key,
                        value: data[key],
                        layers: getLayers(_(key), JSON.parse(data[key]))
                    })
                })
                
                return  _scenes;
            }

            function layer(){
                function init(){
                    Object.assign(this, {
                        index: 0,
                        config:{}, // INPUT_CONFIG
                        mesh: {}, // mesh
                    })
                }
            }
            this.decodeInput = key => {
                let [i,c,id,name,attr] = key.split('_');
                return {id, name, attr}
            }

            this.decodeMesh = (key, name) => {
                let [prefix, vec] = key.split(name);
                let [m, e, id] = prefix.split('_');
                return {id, name, vec};
            }

            this.decodeUIL = (sceneName) => {
                _cache = {
                    data:{},
                    layers:[]
                };
                let _map = Object.keys(data);
                let normalKeys = _map.filter(key => !!key.includes(sceneName));

                const initLayer = (id, name, ext) => {
                    return _cache.layers[id] || (_cache.layers[id] = {config:{}, mesh:{}, index:id, namespace:name, ...ext});
                }
                const setConfig = (id, name, attr,value) => {
                    return initLayer(id, name)['config'][attr] = value;
                }
                const setMesh = (id, name, vec, value) => {
                    return initLayer(id, name)['mesh'][vec] = value;
                }

                const updateShader = (layer, shader) => {
                    layer['shader'] = {};
                    _shader = {};
                    normalKeys.map(key => {
                        if(key.includes(`${shader}/${shader}/`)) {
                            let attr = key.split('/').last();
                            _shader[attr] = data[key];
                        }
                    })
                    layer['shader'][shader] = _shader;
                }

                const updateCustomClass = (layer, customClass, prefix) => {
                    layer['customClass'] = {};
                    let _customClass = {};
                    normalKeys.map(key => {
                        if(key.includes(`${customClass}/${customClass}/`)) {
                            let attr = key.split('/').last();
                            _customClass[attr] = data[key];
                        }
                    })
                    layer['customClass'][customClass] = _customClass;
                }

                normalKeys.map(key => {
                    if(/^INPUT_Config_/.test(key)){
                        let {id, name, attr} = this.decodeInput(key);
                        setConfig(id, name, attr, data[key]);
                    } else if(/^MESH_/.test(key)){
                        let {id, name, vec} = this.decodeMesh(key, sceneName);
                        setMesh(id, name, vec, data[key]);
                    } else if(/_scenelayout_/.test(key)){
                        layersCopy = JSON.parse(data[key]);
                        Object.assign(_cache.data, {...layersCopy});
                    } else if(/_deleted$/.test(key)) {
                        let id = key.match(/_([0-9]+)_/)[1];
                        initLayer(id, sceneName, {deleted: true});
                    } else if(/INPUT_Light_/.test(key)) {
                        let [i, l, e, id, name, attr] = key.split('_');
                        let _data = {}; _data[attr] = data[key];
                        let _layer = initLayer(id, name)
                        _layer['light'] || (_layer['light'] = {}),
                        Object.assign(_layer['light'], _data);
                    }
                })
                _cache.layers.map(layer => {
                    let {shader, customClass} = layer.config;
                    if(shader) {
                        updateShader(layer, shader);
                    }
                    if(customClass) {
                        updateCustomClass(layer, customClass);
                    }
                })

                return _cache;

                // let root = {
                //     MESH: [],
                //     INPUT_Element: [],
                //     INPUT_CONFIG_sl: [],
                //     INPUT_Config: [],
                //     INPUT_P_Element: [],
                //     OTHER: []
                // };
                // const _ = q => normalKeys.filter(key => key.includes(q))
                // root = {
                //     scenes: getScenes(_('scenelayout'))
                // };
                // return _cache;
                // console.log(root);
                // normalKeys.map(key => {
                //     if(/^MESH_Element/.test(key)) {
                //         root['MESH'].push(key.replace(/^MESH_Element_/, ''));
                //     } else if(/^INPUT_P_Element_/.test(key)) {
                //         root['INPUT_P_Element'].push(key.replace(/^INPUT_P_Element_/, ''));
                //     } else if(/^INPUT_Element_/.test(key)){
                //         root['INPUT_Element'].push(key.replace(/^INPUT_Element_/, ''));
                //     } else if(/^INPUT_CONFIG_sl/.test(key)) {
                //         root['INPUT_CONFIG_sl'].push(key.replace(/^INPUT_CONFIG_sl_/, ''));

                //     } else if(/^INPUT_Config/.test(key)) {
                //         root['INPUT_Config'].push(key.replace(/^INPUT_Config_/, ''));
                //     } else {
                //         root['OTHER'].push(key);
                //     }
                // })
                console.log(root)

            };
            
            

        }, 'Static');

        Class(function renderA(data){
            function init(_data){
                console.log(_data);
            }
            init(data);
        },"singleton");



        Class(function Main(){
            
            function displayJSON(json){
                Stage.create('', 'pre').add(
                    Stage.create('json', 'code').html(JSON.stringify(json, null, 2))
                )
                
            }
            !(async function(){
                await UILData.ready();

                let res = UILData.key('input').name('environment').index(1).get();
                UILData.name('demo').set(res);
                
                let ep = UILData.key('element').name('environment').get();
                ep = UILData.name('demo').set(ep);
                displayJSON(ep);

                let a = UILData.decodeUIL('LandingScene_layout');
                displayJSON(a);
                renderA.instance(a);
            })()
           
        });
    </script>
</body>
</html>